package com.usian.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.usian.mapper.*;
import com.usian.pojo.*;
import com.usian.redis.RedisClient;
import com.usian.service.ItemService;
import com.usian.utils.IDUtils;
import com.usian.utils.PageResult;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
//@Transactional
public class ItemServiceImpl implements ItemService {
    @Resource
    TbItemMapper tbItemMapper;
    @Resource
    TbItemDescMapper tbItemDescMapper;
    @Resource
    TbItemParamItemMapper tbItemParamItemMapper;
    @Resource
    TbItemCatmapper tbItemCatmapper;
    @Resource
    TbOrderItemMapper tbOrderItemMapper;
    @Autowired
    AmqpTemplate amqpTemplate;

    @Value("${ITEM_INFO}")
    private String ITEM_INFO;
    @Value("${BASE}")
    private String BASE;
    @Value("${DESC}")
    private String DESC;
    @Value("${PARAM}")
    private String PARAM;
    @Value("${ITEM_INFO_EXPIRE}")
    private Integer ITEM_INFO_EXPIRE;

    @Value("${SETNX_BASC_LOCK_KEY}")
    private String SETNX_BASC_LOCK_KEY;
    @Value("${SETNX_DESC_LOCK_KEY}")
    private String SETNX_DESC_LOCK_KEY;

    @Resource
    private RedisClient redisClient;
    //查询商品并分页
    @Override
    public PageResult selectTbItemAllByPage(int page, int rows) {
        PageHelper.startPage(page,rows);
        QueryWrapper<TbItem> wrapper = new QueryWrapper<>();
        wrapper.eq("status",1);
        wrapper.orderByAsc("cid");
        /*Page<TbItem> tbItemPage = new Page<>(page,rows);
          Page<TbItem> tbItemPage1 = tbItemMapper.selectPage(tbItemPage, wrapper);*/
        List<TbItem> tbItems = tbItemMapper.selectList(wrapper);
        for (TbItem tbItem : tbItems) {
          tbItem.setPrice(tbItem.getPrice()/100);
        }
        PageInfo<TbItem> pageInfo = new PageInfo<TbItem>(tbItems);
        PageResult pageResult = new PageResult();
        pageResult.setPageIndex(pageInfo.getPageNum());
        pageResult.setTotalPage(Long.valueOf(pageInfo.getPages()));
        pageResult.setResult(pageInfo.getList());
        return pageResult;
    }
    //添加商品
    @Override
    public Integer insertTbItem(TbItem tbItem, String desc, String itemParams) {
        //补齐 Tbitem 数据
        Long itemId = IDUtils.genItemId();
        Date date = new Date();
        tbItem.setId(itemId);
        tbItem.setStatus((byte)1);
        tbItem.setUpdated(date);
        tbItem.setCreated(date);
        tbItem.setPrice(tbItem.getPrice()*100);
        Integer tbItemNum = tbItemMapper.insert(tbItem);

        //补齐商品描述对象
        TbItemDesc tbItemDesc = new TbItemDesc();
        tbItemDesc.setItemId(itemId);
        tbItemDesc.setItemDesc(desc);
        tbItemDesc.setCreated(date);
        tbItemDesc.setUpdated(date);
        Integer tbitemDescNum = tbItemDescMapper.insert(tbItemDesc);

        //补齐商品规格参数
        TbItemParamItem tbItemParamItem = new TbItemParamItem();
        tbItemParamItem.setItemId(itemId);
        tbItemParamItem.setParamData(itemParams);
        tbItemParamItem.setUpdated(date);
        tbItemParamItem.setCreated(date);
        Integer itemParamItmeNum =
                tbItemParamItemMapper.insert(tbItemParamItem);
        //添加商品发布消息到mq
        amqpTemplate.convertAndSend("item_exchage","item.add", itemId);
        return tbItemNum + tbitemDescNum + itemParamItmeNum;
    }
//修改回显的数据
    @Override
    public Map<String, Object> preUpdateItem(Long itemId) {
        Map<String, Object> map = new HashMap<>();
        //根据商品 ID 查询商品
        TbItem item = this.tbItemMapper.selectByPrimaryKey(itemId);
        if (item!=null){
            item.setPrice(item.getPrice()/100);
            map.put("item", item);
        }

        //根据商品 ID 查询商品描述
        TbItemDesc itemDesc = this.tbItemDescMapper.selectByPrimaryKey(itemId);
        if (itemDesc!=null) {
            map.put("itemDesc", itemDesc.getItemDesc());
        }
        //根据商品 类目ID 查询商品类目
        TbItemCat itemCat = this.tbItemCatmapper.selectByPrimaryKey(item.getCid());
        if (itemCat!=null) {
            map.put("itemCat", itemCat.getName());
        }
        //根据商品 ID 查询商品规格信息
        QueryWrapper<TbItemParamItem> tbItemParamItemQueryWrapper = new QueryWrapper<>();
        tbItemParamItemQueryWrapper.eq("item_id",itemId);
        List<TbItemParamItem> list = tbItemParamItemMapper.selectList(tbItemParamItemQueryWrapper);
        if (list != null && list.size() > 0) {
            map.put("itemParamItem", list.get(0).getParamData());
        }
        return map;
    }
//修改商品
    @Override
    public Integer updateTbItem(TbItem tbItem, String desc, String itemParams) {
        //补齐 Tbitem 数据
        Date date = new Date();

        tbItem.setStatus((byte)1);
        tbItem.setUpdated(date);

        tbItem.setPrice(tbItem.getPrice()*100);
        Integer tbItemNum = tbItemMapper.updateById(tbItem);

        //补齐商品描述对象
        TbItemDesc tbItemDesc = new TbItemDesc();
        tbItemDesc.setItemId(tbItem.getId());
        tbItemDesc.setItemDesc(desc);
        tbItemDesc.setUpdated(date);
        Integer tbitemDescNum = tbItemDescMapper.updateById(tbItemDesc);

        //补齐商品规格参数
        QueryWrapper<TbItemParamItem> tbItemParamItemQueryWrapper = new QueryWrapper<>();
        tbItemParamItemQueryWrapper.eq("item_id",tbItem.getId());
        TbItemParamItem tbItemParamItem = tbItemParamItemMapper.selectOne(tbItemParamItemQueryWrapper);
        tbItemParamItem.setItemId(tbItem.getId());
        tbItemParamItem.setParamData(itemParams);
        tbItemParamItem.setUpdated(date);
        Integer itemParamItmeNum = tbItemParamItemMapper.updateById(tbItemParamItem);
        //修改商品发布消息到mq
        amqpTemplate.convertAndSend("item_exchage","item.update",tbItem.getId());
        //删除redis里的数据
        redisClient.del(ITEM_INFO + ":" + tbItem.getId() + ":"+ BASE);
        redisClient.del(ITEM_INFO + ":" + tbItem.getId() + ":"+ DESC);
        redisClient.del(ITEM_INFO + ":" + tbItem.getId() + ":"+ PARAM);
        return tbItemNum + tbitemDescNum + itemParamItmeNum;
    }
//删除商品
    @Override
    public Integer deleteItemById(Integer itemId) {
        //删除规格表
        QueryWrapper<TbItemParamItem> tbItemParamItemQueryWrapper = new QueryWrapper<>();
        tbItemParamItemQueryWrapper.eq("item_id",itemId);
        int num1 = tbItemParamItemMapper.delete(tbItemParamItemQueryWrapper);
        //删除商品描述表
        int num2 = tbItemDescMapper.deleteById(itemId);
        //删除商品表
        int num3 = tbItemMapper.deleteById(itemId);
        //删除商品发布消息到mq
        amqpTemplate.convertAndSend("item_exchage","item.delete",itemId);
        //删除redis里的数据
        redisClient.del(ITEM_INFO + ":" + itemId + ":"+ BASE);
        redisClient.del(ITEM_INFO + ":" + itemId + ":"+ DESC);
        redisClient.del(ITEM_INFO + ":" + itemId + ":"+ PARAM);
        return num1+num2+num3;
    }
    //查询商品基本信息
    //逻辑大概是先查redis如果没有查数据库然后保存到redis里
    @Override
    public TbItem selectItemInfo(Long itemId) {
        //查询缓存
        TbItem tbItem = (TbItem) redisClient.get(ITEM_INFO + ":" + itemId + ":"+ BASE);
        if(tbItem!=null){
            return tbItem;
        }
        /**
         * 解决缓存击穿
         */
        if (redisClient.setnx(SETNX_BASC_LOCK_KEY+":"+itemId,itemId,5L)){
            tbItem = tbItemMapper.selectByPrimaryKey(itemId);
            //********************解决缓存穿透************************/
            //如果redis数据库里都是空那么在redis里存null并设置30秒
            if(tbItem == null){
                //把空对象保存到缓存
                redisClient.set(ITEM_INFO + ":" + itemId + ":"+ BASE,new TbItem());
                //设置缓存的有效期
                redisClient.expire(ITEM_INFO + ":" + itemId + ":"+ BASE,30);
                return tbItem;
            }else {
                //把数据保存到缓存
                redisClient.set(ITEM_INFO + ":" + itemId + ":" + BASE, tbItem);
                //设置缓存的有效期
                redisClient.expire(ITEM_INFO + ":" + itemId + ":" + BASE, ITEM_INFO_EXPIRE);
            }
            redisClient.del(SETNX_BASC_LOCK_KEY+":"+itemId);
            return tbItem;
        }else {

            try {

                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
           return selectItemInfo(itemId);
        }
    }
    //查询商品介绍
    @Override
    public TbItemDesc selectItemDescByItemId(Long itemId) {
        //查询缓存
        TbItemDesc tbItemDesc = (TbItemDesc) redisClient.get(
                ITEM_INFO + ":" + itemId + ":"+ DESC);
        if(tbItemDesc!=null){
            return tbItemDesc;
        }
        if (redisClient.setnx(SETNX_DESC_LOCK_KEY+":"+itemId,itemId,5L)) {
            QueryWrapper<TbItemDesc> tbItemDescQueryWrapper = new QueryWrapper<>();
            tbItemDescQueryWrapper.eq("item_id", itemId);
           TbItemDesc itemDesc = tbItemDescMapper.selectByPrimaryKey(itemId);
            if (itemDesc != null) {
                //把数据保存到缓存
                redisClient.set(ITEM_INFO + ":" + itemId + ":" + DESC, itemDesc);
                //设置缓存的有效期
                redisClient.expire(ITEM_INFO + ":" + itemId + ":" + DESC, ITEM_INFO_EXPIRE);

            }else {
                //********************解决缓存穿透************************/
                //如果redis和数据库都没有数据在redis里存null并设置30秒
                //把空对象保存到缓存

                redisClient.set(ITEM_INFO + ":" + itemId + ":" + DESC, new TbItemDesc());
                //设置缓存的有效期
                redisClient.expire(ITEM_INFO + ":" + itemId + ":" + DESC, 30);
            }
            redisClient.del(SETNX_DESC_LOCK_KEY+":"+itemId);
            return itemDesc;
        }else {

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return selectItemDescByItemId(itemId);
        }
    }
    //订单提交之后修改库存
    @Override
    public Integer updateTbItemByOrderId(String orderId) {
        QueryWrapper<TbOrderItem> tbOrderItemQueryWrapper = new QueryWrapper<>();
        tbOrderItemQueryWrapper.eq("order_id",orderId);
        List<TbOrderItem> tbOrderItemList = tbOrderItemMapper.selectList(tbOrderItemQueryWrapper);
        int result = 0;
        for (int i = 0; i < tbOrderItemList.size(); i++) {
            TbOrderItem tbOrderItem =  tbOrderItemList.get(i);
            TbItem tbItem =
                    tbItemMapper.selectByPrimaryKey(Long.valueOf(tbOrderItem.getItemId()));
            tbItem.setNum(tbItem.getNum()-tbOrderItem.getNum());
            result += tbItemMapper.updateById(tbItem);
        }
        return result;
    }
}
